﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Xml.Linq;
using Microsoft.Office.Interop.Word;
using Point = System.Windows.Point;

namespace Puzzler.Plugin.Interface
{
    /// <summary>
    /// Represent the puzzle plugin interface
    /// </summary>
    /// <typeparam name="TModel">Type of the plugin model</typeparam>
    /// <typeparam name="TRenderer">Type of the plugin renderer</typeparam>
    /// <typeparam name="TInputHandler">Type of the plugin input handler (key and mouse)</typeparam>
    /// <typeparam name="TRibbonHandler">Type of the plugin ribbon handler</typeparam>
    /// <typeparam name="TWordAddInHandler">Type of the plugin "Word AddIn" Handler</typeparam>
    /// <typeparam name="TIoHandler">Type for the IO Handler</typeparam>
    public abstract class PuzzlePlugin<TModel, TRenderer, TInputHandler, TRibbonHandler, TWordAddInHandler, TIoHandler, TUpgrate> : 
        IPuzzleContent<TModel, TRenderer, TInputHandler, TRibbonHandler, TWordAddInHandler, TIoHandler>, IPuzzlePlugin
        where TModel : PuzzleModel 
        where TRenderer : PuzzleRenderer<TModel> 
        where TInputHandler : PuzzleInputHandler<TModel> 
        where TRibbonHandler : PuzzleRibbonHandler<TModel>
        where TWordAddInHandler : PuzzleWordAddInHandler<TModel>
        where TIoHandler : PuzzleIOHandler<TModel, TUpgrate> 
        where TUpgrate : PuzzleIOUpgrateHandler<TModel>
    {
        public TModel Model { get; private set; }
        public TRenderer Renderer { get; private set; }
        public TInputHandler InputHandler { get; private set; }
        public TRibbonHandler RibbonHandler { get; private set; }
        public TWordAddInHandler WordAddInHandler { get; private set; }
        public TIoHandler IoHandler { get; private set; }

        /// <summary>
        /// Current editor canvas
        /// </summary>
        public Canvas Canvas
        {
            get { return Renderer.Canvas; }
            set { Renderer.Canvas = value; }
        }

        protected PuzzlePlugin()
        {
            Model = (TModel) Activator.CreateInstance(typeof(TModel));
            Renderer = (TRenderer) Activator.CreateInstance(typeof(TRenderer), Model);
            InputHandler = (TInputHandler) Activator.CreateInstance(typeof(TInputHandler), Model);
            RibbonHandler = (TRibbonHandler) Activator.CreateInstance(typeof(TRibbonHandler), Model);
            WordAddInHandler = (TWordAddInHandler) Activator.CreateInstance(typeof (TWordAddInHandler), Model);
            IoHandler = (TIoHandler) Activator.CreateInstance(typeof (TIoHandler), Model);
        }

        #region Draw

        public void DrawEditorView(Canvas canvas)
        {
            Renderer.DrawEditorView(canvas);
        }

        public IList<Canvas> DrawPuzzleGameViews()
        {
            return Renderer.DrawPuzzleGameViews();
        }

        public IList<Canvas> DrawPuzzleSolutionViews()
        {
            return Renderer.DrawPuzzleSolutionViews();
        }

        #endregion

        #region Input

        public void OnLeftMouseButtonDown(Point point, MouseButtonEventArgs e)
        {
            InputHandler.OnLeftMouseButtonDown(point, e);
        }

        public void OnLeftMouseButtonUp(Point point, MouseButtonEventArgs e)
        {
            InputHandler.OnLeftMouseButtonUp(point, e);
        }

        public void OnRightMouseButtonDown(Point point, MouseButtonEventArgs e)
        {
            InputHandler.OnRightMouseButtonDown(point, e);
        }

        public void OnRightMouseButtonUp(Point point, MouseButtonEventArgs e)
        {
            InputHandler.OnRightMouseButtonUp(point, e);
        }

        public void OnMouseMove(Point point, MouseEventArgs e)
        {
            InputHandler.OnMouseMove(point, e);
        }

        public void OnMouseWheel(Point point, MouseWheelEventArgs e)
        {
            InputHandler.OnMouseWheel(point, e);
        }

        public void OnKeyDown(KeyEventArgs e)
        {
            InputHandler.OnKeyDown(e);
        }

        public void OnKeyUp(KeyEventArgs e)
        {
            InputHandler.OnKeyUp(e);
        }

        #endregion

        #region Ribbon

        public void OnRibbonButtonClick(string key)
        {
            RibbonHandler.OnRibbonButtonClick(key);
        }

        public void OnRibbonChecked(string key)
        {
            RibbonHandler.OnRibbonChecked(key);
        }

        public void OnRibbonUnchecked(string key)
        {
            RibbonHandler.OnRibbonUnchecked(key);
        }

        public void OnRibbonUnselected(string key)
        {
            RibbonHandler.OnRibbonUnselected(key);
        }

        public void OnRibbonSelected(string key)
        {
            RibbonHandler.OnRibbonSelected(key);
        }

        #endregion

        #region Word AddIn

        public void AddGameContent(Range range, IList<Canvas> images)
        {
            WordAddInHandler.AddGameContent(range, images);
        }

        public void AddSolutionContent(Range range, IList<Canvas> images)
        {
            WordAddInHandler.AddSolutionContent(range, images);
        }

        #endregion
        
        #region Model

        public void Update(PuzzleData data)
        {
            Model.Update(data);
        }

        #endregion

        #region Plugin Action

        public virtual void OnInitialized()
        {
            Model.OnInitialized();
            Renderer.OnInitialized();
            InputHandler.OnInitialized();
            RibbonHandler.OnInitialized();
            IoHandler.OnInitialized();
            WordAddInHandler.OnInitialized();
        }

        public virtual void OnDone()
        {
            Model.OnDone();
            Renderer.OnDone();
            InputHandler.OnDone();
            RibbonHandler.OnDone();
            IoHandler.OnDone();
            WordAddInHandler.OnDone();
        }

        public virtual void OnActivated()
        {
            Model.OnActivated();
            Renderer.OnActivated();
            InputHandler.OnActivated();
            RibbonHandler.OnActivated();
            IoHandler.OnActivated();
            WordAddInHandler.OnActivated();
        }

        public virtual void OnDeactivated()
        {
            Model.OnDeactivated();
            Renderer.OnDeactivated();
            InputHandler.OnDeactivated();
            RibbonHandler.OnDeactivated();
            IoHandler.OnDeactivated();
            WordAddInHandler.OnDeactivated();
        }

        #endregion

        #region Implementation of IPuzzleIOHandler

        public void SaveToXml(XElement element)
        {
            IoHandler.SaveToXml(element);
        }

        public void LoadFromXml(XElement element)
        {
            IoHandler.LoadFromXml(element);
        }

        public void SaveToBinary(StreamWriter writer)
        {
            IoHandler.SaveToBinary(writer);
        }

        public void LoadFromBinary(StreamReader reader)
        {
            IoHandler.LoadFromBinary(reader);
        }

        #endregion
    }
}
